package com.hhkj.study.admin.resource.service.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.hhkj.study.admin.resource.common.CommonValidateHandler;
import com.hhkj.study.admin.resource.entity.ResourceCourseLive;
import com.hhkj.study.admin.resource.entity.ResourceCourseVideo;
import com.hhkj.study.admin.resource.event.AsyncUpdateVideoEvent;
import com.hhkj.study.admin.resource.event.EventPublisher;
import com.hhkj.study.admin.resource.excel.ResourceCourseLiveExcelRes;
import com.hhkj.study.admin.resource.excel.ResourceLivePlayBackExcelRes;
import com.hhkj.study.admin.resource.model.podo.ResourceCourseLiveDo;
import com.hhkj.study.admin.resource.model.podo.ResourceCourseLivePo;
import com.hhkj.study.admin.resource.model.req.ResourceCourseLiveReq;
import com.hhkj.study.admin.resource.model.res.ResourceCourseLiveRes;
import com.hhkj.study.admin.resource.service.base.ResourceCourseLiveService;
import com.hhkj.study.admin.resource.service.biz.ResourceCourseLiveBizService;
import com.hhkj.study.admin.resource.service.extend.ResourceCourseLiveExtendService;
import com.hhkj.study.admin.resource.service.extend.ResourceCourseVideoExtendService;
import com.hhkj.study.common.cache.GlobalCache;
import com.hhkj.study.common.model.res.ExcelImportResultRes;
import com.ruoyi.common.base.biz.service.biz.BaseBizServiceImpl;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.enums.DictCodeEnum;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.excl.utils.ExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
* ResourceCourseLiveBizServiceImpl
*
* @author SERVER
* @since 2024-09-06
*/
@Slf4j
@Service
public class ResourceCourseLiveBizServiceImpl extends BaseBizServiceImpl<ResourceCourseLive, ResourceCourseLiveReq, ResourceCourseLiveRes, ResourceCourseLiveDo, ResourceCourseLivePo, ResourceCourseLiveService, ResourceCourseLiveExtendService> implements ResourceCourseLiveBizService {

    @Resource
    private GlobalCache globalCache;

    @Resource
    private CommonValidateHandler commonValidateHandler;

    @Resource
    private ResourceCourseVideoExtendService videoExtendService;

    @Resource
    private EventPublisher eventPublisher;

    /** 视频类型中回放值 */
    private static final String VIDEO_PLAY_BACK_VALUE = "直播";

    @Override
    public boolean updatePublishFlag(ResourceCourseLiveReq req) {
        ResourceCourseLive resourceCourseLive = this.getExtendService().getByIdNotNull(req.getId());
        if (resourceCourseLive.getPublishedFlag().equals(req.getPublishedFlag())) {
            throw new GlobalException(SysConst.Flag.IS.getFlag().equals(req.getPublishedFlag()) ?
                    "已上架" : "已下架");
        }
        LambdaUpdateWrapper<ResourceCourseLive> liveUpdate = new LambdaUpdateWrapper<>();
        liveUpdate.eq(ResourceCourseLive::getId, req.getId())
                .set(ResourceCourseLive::getPublishedFlag, req.getPublishedFlag());
        return this.getService().update(liveUpdate);
    }

    @Override
    public void export(ResourceCourseLiveReq req, HttpServletResponse response) {
        List<ResourceCourseLiveRes> courseLiveResList = list(req);
        if (CollectionUtil.isEmpty(courseLiveResList)) {
            throw new GlobalException("没有数据");
        }
        ExcelUtils.exportExcelRuoYi(response, BeanUtil.copyToList(courseLiveResList, ResourceCourseLiveExcelRes.class), ResourceCourseLiveExcelRes.class , "直播课信息", "直播课信息");
    }

    @Override
    public ExcelImportResultRes importCourseLive(MultipartFile file, HttpServletRequest request) {
        List<ResourceCourseLiveExcelRes> excelResList = ExcelUtils.importExcelRuoYi(file, ResourceCourseLiveExcelRes.class, 1);
        if (CollectionUtil.isEmpty(excelResList)) {
            throw new GlobalException("没有数据");
        }
        // 导入信息结果
        ExcelImportResultRes excelImportResultRes = commonValidateHandler.validate(excelResList, (name, courseType) -> ObjectUtil.isNotNull(this.getExtendService().getByNameCourseType(name, courseType)));
        if (CollectionUtil.isEmpty(excelImportResultRes.getErrorList())) {
            this.getService().saveBatch(BeanUtil.copyToList(excelResList, ResourceCourseLive.class));
        }
        return excelImportResultRes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ExcelImportResultRes batchImportPlayBack(MultipartFile file, HttpServletRequest request) {
        List<ResourceLivePlayBackExcelRes> livePlayBackExcelResList = ExcelUtils.importExcelRuoYi(file, ResourceLivePlayBackExcelRes.class, 1);
        if (CollectionUtil.isEmpty(livePlayBackExcelResList)) {
            throw new GlobalException("没有数据");
        }
        ExcelImportResultRes excelImportResultRes = commonValidateHandler.validate(livePlayBackExcelResList, (name, courseType) -> {
            ResourceCourseLive courseLive = this.getExtendService().getByNameCourseType(name, courseType);
            return ObjectUtil.isNotNull(courseLive) && SysConst.Flag.NO.getFlag().equals(courseLive.getPlaybackFlag());
        });
        // 先要新增视频同时计算视频大小时长 并且更新直播表关联新增的视频
        List<ResourceCourseLive> courseLiveList = Lists.newArrayList();
        List<ResourceCourseVideo> courseVideoList = Lists.newArrayList();
        if (CollectionUtil.isEmpty(excelImportResultRes.getErrorList())) {
            livePlayBackExcelResList.forEach(livePlayBackExcelRes -> {
                ResourceCourseLive resourceCourseLive = this.getExtendService().getByNameCourseType(livePlayBackExcelRes.getLiveName(), livePlayBackExcelRes.getCourseType());
                if (ObjectUtil.isNull(resourceCourseLive)) {
                    return;
                }
                ResourceCourseVideo courseVideo = new ResourceCourseVideo();
                courseVideo.setCourseType(resourceCourseLive.getCourseType());
                courseVideo.setYear(resourceCourseLive.getYear());
                // 回放导入的视频名为该直播名后加回放两字后缀
                String videoName = resourceCourseLive.getName() + VIDEO_PLAY_BACK_VALUE;
                courseVideo.setName(videoName);
                courseVideo.setTeacherId(resourceCourseLive.getTeacherId());
                courseVideo.setUrl(livePlayBackExcelRes.getPlayBackUrl());
                courseVideo.setUploadTime(new Date());
                // 通过名称和code获取对应的id
                Map<String, Long> idNameMap = globalCache.getIdByName(Lists.newArrayList(VIDEO_PLAY_BACK_VALUE), Lists.newArrayList(DictCodeEnum.VIDEO_TYPE.getCode()));
                courseVideo.setType(idNameMap.get(VIDEO_PLAY_BACK_VALUE));

                courseLiveList.add(resourceCourseLive);
                courseVideoList.add(courseVideo);
            });
        }
        boolean isSuccess = videoExtendService.saveBatchVideoNameUnique(courseVideoList);
        if (isSuccess) {
            updateBatchLive(courseLiveList, courseVideoList);
            eventPublisher.sendEvent(new AsyncUpdateVideoEvent(this, courseVideoList));
        }
        return excelImportResultRes;
    }

    @Override
    public ResourceCourseLiveRes getLiveByVideoId(Long videoId) {
        LambdaQueryWrapper<ResourceCourseLive> resourceCourseLiveQuery = new LambdaQueryWrapper<>();
        resourceCourseLiveQuery.eq(ResourceCourseLive::getVideoId, videoId).last("LIMIT 1");
        ResourceCourseLive resourceCourseLive = this.getService().getOne(resourceCourseLiveQuery);
        return BeanUtil.toBean(resourceCourseLive, ResourceCourseLiveRes.class);
    }

    /**
     * 批量更新直播表 视频id和是否有回放字段
     * @param courseLiveList
     * @param resourceCourseVideoList
     */
    private void updateBatchLive(List<ResourceCourseLive> courseLiveList, List<ResourceCourseVideo> resourceCourseVideoList) {
        IntStream.range(0, courseLiveList.size()).forEach(i -> {
            ResourceCourseVideo courseVideo = resourceCourseVideoList.get(i);
            courseLiveList.get(i).setVideoId(courseVideo.getId());
            courseLiveList.get(i).setPlaybackFlag(SysConst.Flag.IS.getFlag());
        });
        this.getService().updateBatchById(courseLiveList);
    }


    @Override
    protected void afterPage(List<ResourceCourseLiveRes> liveResList) {
        supplyLive(liveResList);
    }

    @Override
    protected void afterGetById(ResourceCourseLiveRes resourceCourseLiveRes) {
        supplyLive(Lists.newArrayList(resourceCourseLiveRes));
    }

    @Override
    protected void afterList(List<ResourceCourseLiveRes> liveResList) {
        supplyLive(liveResList);
    }

    @Override
    protected void beforeSave(ResourceCourseLiveReq resourceCourseLiveReq) {
        checkNameUnique(resourceCourseLiveReq);
    }



    @Override
    protected void beforeUpdate(ResourceCourseLiveReq resourceCourseLiveReq) {
        ResourceCourseLive resourceCourseLive = this.getExtendService().getByIdNotNull(resourceCourseLiveReq.getId());
        if (!StrUtil.equals(resourceCourseLive.getName(), resourceCourseLiveReq.getName())) {
            checkNameUnique(resourceCourseLiveReq);
        }
    }

    /**
     * 检验名称的唯一性
     * @param resourceCourseLiveReq
     */
    private void checkNameUnique(ResourceCourseLiveReq resourceCourseLiveReq) {
        ResourceCourseLive courseLive = this.getExtendService().getByNameCourseType(resourceCourseLiveReq.getName(), resourceCourseLiveReq.getCourseType());
        if (ObjectUtil.isNotNull(courseLive)) {
            throw new GlobalException("直播名称已存在");
        }
    }
    /**
     * 补充直播其他参数
     * @param liveResList
     */
    private void supplyLive(List<ResourceCourseLiveRes> liveResList){
        Map<Long, String> dictMap = globalCache.cacheDictMap(Lists.newArrayList(DictCodeEnum.COURSE_TYPE.getCode(), DictCodeEnum.LIVE_TYPE.getCode()));
        liveResList.forEach(liveRes -> {
            liveRes.setCourseTypeName(dictMap.get(liveRes.getCourseType()));
            liveRes.setTypeName(dictMap.get(liveRes.getType()));
        });
    }

}